package br.com.usjt.sge.util.cpf;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

/**
 * Classe responsavel por implementar um validador de CPF.
 * @author cicero
 *
 */
public class CPFValidator implements Validator {

	/**
	 * Metodo que valida o CPF.
	 * @param context - contexto da aplicacao
	 * @param component - componente jsf
	 * @param value - objeto cpf a ser validado
	 * @throws validatorException
	 */
	@Override
	public void validate(FacesContext context, UIComponent component, Object value)
			throws ValidatorException {
		
		if (value == null) {
			
			return;
			
		}
		
		String cpf = (String) value;
		
		if (isCPFPadrao(cpf)|| cpf.length() != 11 || !calcularDigitoVerificador(cpf.substring(0, 9)).equals(cpf.substring(9, 11))) {
			
			throw new ValidatorException(
					new FacesMessage(FacesMessage.SEVERITY_ERROR,"CPF inválido.","Favor informar um CPF válido."));
			
			
		}
		
	}
	
	/**
	 * Metodo para verificar se um CPF e padrao.
	 * @param cpf - CPF a ser verificado
	 * @return boolean indicando se o CPF e padrao
	 */
	private boolean isCPFPadrao(String cpf) {
		
		if (cpf.equals("11111111111") || cpf.equals("22222222222")
					        || cpf.equals("33333333333")
					        || cpf.equals("44444444444")
					        || cpf.equals("55555555555")
					        || cpf.equals("66666666666")
					        || cpf.equals("77777777777")
					        || cpf.equals("88888888888")
					        || cpf.equals("99999999999")) {
			return true;
					        	
					        	
	    }
		
		return false;
		
	}

	/**
	 * Metodo responsavel por calcular o digito verificador do numero do CPF.
	 * @param num - numero do cpf
	 * @return String com os digitos verificadores do CPF
	 */
	private String calcularDigitoVerificador(String num) {
		
		Integer primDig, segDig;
		int soma = 0, peso = 10;
		
		for (int i = 0; i < num.length(); i++) {
				
			soma += Integer.parseInt(num.substring(i, i + 1)) * peso--;
			
		}
		
		if (soma % 11 == 0 | soma % 11 == 1) {
			
			primDig = new Integer(0);
			
		} else {
			
			primDig = new Integer(11 - (soma % 11));
			
		}
		
		soma = 0;
		peso = 11;
		
		for (int j = 0; j < num.length(); j++) {
			
			soma += Integer.parseInt(num.substring(j, j + 1)) * peso--;
			
		}
		
		soma += primDig.intValue() * 2;
		
		if (soma % 11 == 0 | soma % 11 == 1) {
			
			segDig = new Integer(0);
			
		} else {
			
			segDig = new Integer(11 - (soma % 11));
			
		}
		
		return primDig.toString() + segDig.toString();
	}

}
